package http

import (
	"gitee.com/zhongguo168a/go-nodex/nodex"
	"gitee.com/zhongguo168a/go-nodex/nodex/chanrpc"
	"gitee.com/zhongguo168a/go-nodex/nodex/server"
	"gitee.com/zhongguo168a/gocodes/datax"
	"gitee.com/zhongguo168a/gocodes/datax/jsonmap"
	"gitee.com/zhongguo168a/gocodes/myx/errorx"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"net/http"
)

type MsgHandle struct {
	nodex.MsgHandle
	//
}

// Do 马上以非阻塞方式处理消息
func (mh *MsgHandle) Do(request *server.Request) (err error) {
	var (
		msgId = request.Message.GetMsgID()
		//token = request.Message.GetToken()
	)
	//if request.Message.GetToken() != "" {
	//	request.Conn.GetProperty().Store("token", token)
	//}
	router := request.Route.(*nodex.Router)
	ctx, GetContextErr := mh.GetContext(request, router)
	if GetContextErr != nil {
		err = errors.Wrap(GetContextErr, "get context")
		return
	}
	args := request.Args

	var reply interface{}
	reply, newerr := router.NewReply()
	if newerr != nil {
		return errorx.Wrap(newerr, "new reply", datax.M{"Route": msgId})
	}
	var replyerr error
	switch router.Config.CallMode {
	case nodex.CONNECTION:
		replyerr = router.Call(ctx, args, reply)
		mh.resp(router, request, reply, replyerr)
	case nodex.GOROUTINE:
		// 由于http本身就会创建新的协程，这里就不需要了
		replyerr = router.Call(ctx, args, reply)
		mh.resp(router, request, reply, replyerr)
	case nodex.CHANRPC:
		var (
			chanrpc *chanrpc.Server
		)
		rpc := ctx.GetRPC()
		if !rpc.Contains(msgId) {
			err = errors.New("rpc handler not found: " + msgId)
			return
		}
		results, callerr := chanrpc.Open(1).CallN(msgId, ctx, args)
		if callerr != nil {
			replyerr = callerr
		} else {
			if results != nil {
				r1, _ := results[1].(error)
				replyerr = r1
				reply = results[0]
			}
		}
		mh.resp(router, request, reply, replyerr)
	}

	return
}

func (mh *MsgHandle) resp(router *nodex.Router, request *server.Request, reply interface{}, replyerr error) {
	if router.ReturnNum == 0 { //  无返回值

	} else {
		conn := request.Context.(*gin.Context)
		var replyObj map[string]interface{}
		if replyerr != nil {
			replyObj = map[string]interface{}{}
			replyObj["error"] = replyerr.Error()
			conn.JSON(http.StatusOK, replyObj)
		} else {
			if reply != nil {
				stringresp, ok := reply.(*nodex.HttpResultString)
				if ok {
					conn.String(http.StatusOK, stringresp.Data)
				} else {
					replyObj = map[string]interface{}{}
					result := map[string]interface{}{}
					err := jsonmap.StructToMap(reply, result)
					if err != nil {
						replyObj["error"] = "struct to map: " + err.Error()
					} else {
						replyObj["result"] = result
					}
					conn.JSON(http.StatusOK, replyObj)
				}
			}
		}
	}

	return
}
